/*================================================================
*   Copyright (C) 2022 Sangfor Ltd. All rights reserved.
*   
*   文件名称：oj_model.hpp
*   创 建 者：wudu
*   创建日期：2022年04月24日
*   描    述：
*
================================================================*/
#pragma once

/*
 * 1.试题信息如何描述
 * 2.如何将多个试题信息组织起来
 * */


#include <iostream>
#include <string>
#include <unordered_map>
#include <fstream>

#include "oj_tools.hpp"

using namespace std;

/*
 * 描述试题信息的结构体
 * */
struct Question{
    //题目ID
    string id_;
    //题目名称
    string title_;
    //题目的难易程度
    string star_;

    //题目所在路径
    string path_;

    //题目的描述
    string desc_;

    //题目预定义的头部代码
    string header_;
    //题目预定义的尾
    string tail_;
};

/*
 * 1.从文件当中读取试题信息, 将试题信息放到unordered_map
 * 2.提供接口给http模块
 *   2.1 获取全部试题信息的接口
 *   2.2 获取单个试题信息的接口
 * */
class OjModel{
    public:
        OjModel(){
            //读文件， oj_config.cfg , 将试题信息读回来
            // ./oj_data/oj_config.cfg
            bool ret = Load("./oj_data/oj_config.cfg");
            if(ret == false){
                printf("Load config.cfg failed\n");
                exit(1);
            }
        }

        ~OjModel(){

        }

        /*
         * 提供给HTTP模块获取全部试题信息的函数（接口）
         * */
        bool GetAllQuestions(vector<Question>& vec){
            //1.遍历unordered_map, 将value发到vec当中
            for(const auto& kv : all_ques_){
                vec.push_back(kv.second);
            }
            //2.排序
            sort(vec.begin(), vec.end(), [](const Question& l, const Question& r){
                        return stoi(l.id_) < stoi(r.id_);
                    });
            return true;
        }

        /*
         * 提供给HTTP模块获取单个试题信息的函数（接口）
         * */
        bool GetOneQuestion(const string& id, Question* ques){
            auto iter = all_ques_.find(id);
            if(iter == all_ques_.end()){
                return false;
            }

            *ques = iter->second;
            return true;
        }
    private:
        /*
         * 加载配置文件，并且读文件
         * */
        bool Load(const string& filename){
            /*
             * 1.fopen, fwrite, fread, fseek, fclose
             * 2.open, write, read, lseek, close
             * 3.C++ 文件流 istream
             * */

            //1.打开试题的配置文件
            ifstream file(filename.c_str());
            if(!file.is_open()){
                perror("open");
                return false;
            }

            //2.代码能走到这里， 说明文件打开成功了。一行一行的读文件内容
            string line;
            while(getline(file, line)){
                //2.1 切分一行内容， 得到题号，题目名称， 难以程度，路径
                vector<string> output;
                StringUtil::Spilt(line, " ", &output);
                //2.2 创建Question对象， 将内容存放进去
                Question ques;
                ques.id_ = output[0];
                ques.title_ = output[1];
                ques.star_ = output[2];
                ques.path_ = output[3];

                //2.3 读ques.path_下的文件desc， head.cpp, tail.cpp
                FileUtil::ReadFile(ques.path_+"/desc.txt", &ques.desc_);
                FileUtil::ReadFile(ques.path_+"/header.cpp", &ques.header_);
                FileUtil::ReadFile(ques.path_+"/tail.cpp", &ques.tail_);

                //2.4 保存在unordered_map当中
                all_ques_[ques.id_] = ques;
            }

            return true;
        }
    private:
        /*
         * string ， key，描述题目的ID
         * Question, value , 描述题目的具体信息
         * */
        unordered_map<string, Question> all_ques_;
};























